'use client'

import useSWR from "swr"
import { ReactNode, useEffect, useState } from "react"
import { createContext, useContext, useContextSelector } from "use-context-selector"

import { App, ChatMessage, ChatSession } from "@prisma/client"
import { fetchApps, fetchChatMessages, fetchChatSessions } from "@/lib/fetchers/chat"

type AppContextValue = {
    apps: App[]

    currentApp: App | null
    setCurrentApp: (app: App | null) => void

    currentChatSession: ChatSession | null
    setCurrentChatSession: (chatSession: ChatSession) => void

    chatSessions: ChatSession[]
    chatMessages: ChatMessage[]
}

const AppContext = createContext<AppContextValue>({} as AppContextValue)

export const AppContextProvider = ({ children }: { children: ReactNode }) => {
    const [currentApp, setCurrentApp] = useState<App | null>(null)
    const [currentChatSession, setCurrentChatSession] = useState<ChatSession | null>(null)

    const { data: apps, mutate: mutateApps } = useSWR({ url: '/api/apps', params: {} }, fetchApps)
    const { data: chatSessions, mutate: mutateChatSessions } = useSWR({ url: '/api/chat-sessions', params: { appId: currentApp?.id ?? '' } }, fetchChatSessions)
    const { data: chatMessages, mutate: mutateChatMessages } = useSWR({ url: '/api/chat-messages', params: { sessionId: currentChatSession?.id ?? '' } }, fetchChatMessages)

    useEffect(() => setCurrentChatSession(null), [currentApp, setCurrentChatSession])

    return (
        <AppContext.Provider value={{
            apps: (apps ? apps : []),

            currentApp,
            setCurrentApp,

            currentChatSession,
            setCurrentChatSession,

            chatSessions: (chatSessions ? chatSessions : []),
            chatMessages: (chatMessages ? chatMessages : []),
        }}> {children} </AppContext.Provider >
    )
}

export const useAppContext = () => {
    const context = useContext(AppContext)
    if (!context) {
        throw new Error('use AppContext inside AppContextProvider')
    }
    return context
}

export const useAppContextSelector: <T>(selector: (value: AppContextValue) => T) => T = (selector) => {
    return useContextSelector(AppContext, selector)
}